package com.ocp.socket.common.utils;

import com.alibaba.fastjson.JSON;
import com.example.app.base.ResultStatus;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import com.ocp.socket.common.Constants;
import com.ocp.socket.common.bean.DevInfo;
import com.ocp.socket.common.bean.UserInfo;
import com.ocp.socket.common.enums.MsgTypeEnum;
import com.ocp.socket.common.enums.ResultStatusEnum;
import org.apache.commons.lang3.StringUtils;
import org.apache.mina.core.session.IoSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * @author: lichong
 * @email: li_chong@massclouds
 * @Date: 2019/3/12 22:51
 * @Description:
 */
public class SessionUtil {
    private static final Logger logger = LoggerFactory.getLogger(SessionUtil.class);

    /**
      *  app的在线连接session， key为牧场id
     */
    private static Multimap<Integer, IoSession> appSessions = ArrayListMultimap.create();

    /**
     *  设备的在线连接session， key为SN码
     */
    private static Map<String, IoSession> deviceSessions = new HashMap<>(16);

    /**
     * 根据牧场id获取该牧场用户的连接session
     * @param orgId
     * @return
     */
    public static List<IoSession> getAppSessionsByOrgId(Integer orgId) {
        return (List<IoSession>)appSessions.get(orgId);
    }

    /**
     * 根据设备编码获取对应的连接session
     * @param snNo  设备编码
     * @return
     */
    public static IoSession getDeviceSessionBySnNo(String snNo) {
        return deviceSessions.get(snNo);
    }

    /**
     * 添加app连接的session
     * @param orgId     组织id
     * @param session   socket连接的session
     */
    public static void addAppSessionMap(Integer orgId, IoSession session) {
        if (orgId == null || session == null) {
            return;
        }
        appSessions.put(orgId, session);
    }

    /**
     * 添加app连接的session
     * @param snNo     sn码
     * @param session   socket连接的session
     */
    public static void addDeviceSessionMap(String snNo, IoSession session) {
        if (StringUtils.isBlank(snNo) || session == null) {
            return;
        }
        deviceSessions.put(snNo, session);
    }

    /**
     * 删除session
     * @param session
     */
    public static void removeSession (IoSession session) {
        //获取attribute信息
        Object object = session.getAttribute(Constants.ATTRIBUTE_KEY_AUTH);
        if (object != null) {
            if (object instanceof UserInfo) {
                UserInfo userInfo = (UserInfo) object;
                appSessions.remove(userInfo.getOrgId(), session);
                logger.info("openId为{}的用户退出连接！！", userInfo.getOpenId());
                return;
            }
            if (object instanceof DevInfo) {
                DevInfo devInfo = (DevInfo) object;
                deviceSessions.remove(devInfo.getSnNo());
                logger.info("设备断开连接，deviceInfo:{}", JSON.toJSONString(devInfo));
                return;
            }
            logger.error("删除session失败，object:{}", JSON.toJSONString(object));
        } else {
            logger.error("删除session时获取Attribute信息失败，session:{}", session);
        }
        logger.info("设备的连接数量：{}, 用户的连接数量：{}", deviceSessions.size(), appSessions.size());
    }

    /*****
     * 根据牧场ID给app用户发送消息内容
     * @param session
     * @param orgId
     * @param msg
     */
    public static void sendAppUserMsgByOrgId(IoSession session, Integer orgId, String msg){
        //根据牧场id获取该牧场下用户的连接session
        List<IoSession> sessions = getAppSessionsByOrgId(orgId);
        if (CollectionUtils.isEmpty(sessions)) {
            return;
        }
        for (IoSession ioSession : sessions) {
            sendAppMsg(ioSession, msg);
        }
    }

    /**
     * session推送信息
     * @param session
     * @param msg
     */
    public static void sendAppMsg(IoSession session, String msg) {
        try{
            session.write(msg);
            logger.debug("给app发送信息，发送成功======================================,sessionId:{}", session.getId());
        }catch (Exception e){
            logger.error("根据牧场id给app发送信息失败，sessionId:{}, msg:{}", session.getId(), msg, e);
            session.closeNow();
        }
    }

    /**
     * 忽略发送的消息
     * @param orgId
     * @param msg
     */
    public static void sendAppUserMsgExceptIgnoreByOrgId(Integer orgId, String msg) {
        //根据牧场id获取该牧场下用户的连接session
        List<IoSession> sessions = getAppSessionsByOrgId(orgId);
        if (CollectionUtils.isEmpty(sessions)) {
            return;
        }
        UserInfo userInfo = null;
        for (IoSession session : sessions) {
            userInfo = (UserInfo) session.getAttribute(Constants.ATTRIBUTE_KEY_AUTH);
            if (userInfo.getIfSendMsg() == Constants.USER_IF_SEND_MSG_IGNORE) {
                continue;
            }
            sendAppMsg(session, msg);
        }
    }

    /**
     * 检测 app的账户是否已经存在连接，如果存在给他发送在别处登录的消息
     * @param orgId     牧场id
     */
    public static void checkAppSnNoConnected(Integer orgId, String openId) {
        List<IoSession> sessions = getAppSessionsByOrgId(orgId);
        UserInfo userInfo = null;
        String msg = CommonUtils.toMsg(MsgTypeEnum.I.getTypeCode(), openId, DateUtil.getNowStr("yyyyMMddHHmmss"), JSON.toJSON(new ResultStatus(ResultStatusEnum.APP_LOGIN_ORTHER)).toString());
        for (IoSession session : sessions) {
            userInfo = (UserInfo) session.getAttribute(Constants.ATTRIBUTE_KEY_AUTH);
            if (userInfo != null && openId.equals(userInfo.getOpenId())) {
                sendAppMsg(session, msg);
            }
        }
    }


}
